home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1996 August: Tool Chest / Apple_Developer_Group_August_1996_Tool_Chest.iso / Sample Code / Snippets / Toolbox / Calc ControlRgn / Calc ControlRgn.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-07  |  9.3 KB  |  258 lines  |  [TEXT/CWIE]

  1. /*************************************************************************
  2. **    Apple Macintosh Developer Technical Support
  3. **
  4. **    A CalcControl Rgn Sample
  5. **
  6. **    by Matthew Xavier Mora, 
  7. **     Apple Developer Technical Support 
  8. **     mxmora@apple.com
  9. **
  10. **    File:        Calc ControlRgn.c
  11. **
  12. **    Copyright © 1995-1996 Apple Computer, Inc.
  13. **    All rights reserved.
  14. **
  15. **    You may incorporate this sample code into your applications without
  16. **    restriction, though the sample code has been provided "AS IS" and the
  17. **    responsibility for its operation is 100% yours.  However, what you are
  18. **    not permitted to do is to redistribute the source as "DSC Sample Code"
  19. **    after having made changes. If you're going to re-distribute the source,
  20. **    we require that you make it clear in the source that the code was
  21. **    descended from Apple Sample Code, but that you've made changes.
  22. **
  23. **  This sample shows how to call a CDEF to get the control's Region.
  24. ** 
  25. **    Version History
  26. **
  27. **     Date        Initials    Comments
  28. ** ----------------------------------------------------------------------
  29. **     02-28-96    mxm            added more comments and error checking
  30. **  05-07-96    mxm         got it ready for the cd
  31. **
  32. **************************************************************************/
  33.  
  34. #include "SimpleApp.h"
  35.  
  36. #define kPaintRegionOffset     ( 200 ) 
  37. #define kNoOffset             ( 0 )
  38. #define kNextButtonOffset    ( 50 )
  39. #define kScrollBarFudge     ( 15 )
  40. #define kMemorySystemErrMsg    "\pMemory Manager error"
  41. #define    kOurWindowTitle        "\pCalculate a Control's Region Sample"
  42. #define kBadThingsMsg        "\pBad things happened"
  43.  
  44. // This is a quick macro for a function that is defined in the 
  45. // next release of SimpleApp
  46.  
  47. #define SAGetObjectRef(a)      ((**a).buttonObject)
  48.  
  49.  
  50.  pascal SInt16 DoButtonHit(ButtonItemRef me, SInt32  modifiers);
  51.  
  52.  
  53. //-------------------------------------------------------------------------
  54. // This function checks MemError and reports any errors returned
  55. //-------------------------------------------------------------------------
  56.     static OSErr CheckMemoryError(void)
  57. //-------------------------------------------------------------------------
  58. {
  59.     OSErr     err;
  60.     
  61.     err = MemError();
  62.     if (err) {
  63.         ErrorMessage(kMemorySystemErrMsg,err,kSANonFatalError);
  64.     }    
  65.     return err;
  66. }
  67.  
  68. //-------------------------------------------------------------------------
  69. // A utility routine to lock a Handle and report any errors. It returns the 
  70. // the state of the handle before it was locked so you can reset the handle
  71. // to its original state.
  72. //-------------------------------------------------------------------------
  73.     static OSErr MyLockHandle(Handle theHandle,SInt8 * state)
  74. //-------------------------------------------------------------------------
  75. {
  76.     OSErr     err = noErr;
  77.     SInt8     tempState;
  78.     
  79.     tempState = HGetState(theHandle);                    // remember the state
  80.     err = CheckMemoryError();                            // alert the user if error
  81.     if (err == noErr) {
  82.         HLock(theHandle);
  83.         err = CheckMemoryError();
  84.     }    
  85.     if (state) {
  86.         *state = tempState;
  87.     }
  88.     return err;
  89. }
  90.  
  91. //-------------------------------------------------------------------------
  92. // A utility routine to Set a Handle state and report any errors. 
  93. //-------------------------------------------------------------------------
  94.     static OSErr MySetHandleState(Handle theHandle,SInt8  state)
  95. //-------------------------------------------------------------------------
  96. {
  97.     OSErr     err = noErr;
  98.     
  99.     HSetState(theHandle,state);                    // remember the state
  100.     err = CheckMemoryError();                    // report any errors
  101.     return err;                                    // return error
  102. }
  103.  
  104. //-------------------------------------------------------------------------
  105. // GetControlRgn takes a control handle and an existing Rgn
  106. // as parameters and will return in the control's rgn    
  107. //-------------------------------------------------------------------------    
  108.     static    OSErr GetControlRegion(ControlHandle ch,RgnHandle theRgn)
  109. //-------------------------------------------------------------------------
  110. {
  111.     Handle             cdefHandle;                                // Handle to the control Proc
  112.     SInt16             errorState = noErr ;                     // preset error state
  113.  
  114.     if ( (ch != nil) && (theRgn != nil) ) {                    // make sure we have a control and Rgn
  115.         cdefHandle = (**ch).contrlDefProc;                     // Get the control's Handle
  116.         if (!*cdefHandle) {                                    // lets load it in if its not 
  117.             LoadResource(cdefHandle);    
  118.             errorState = ResError();                        // check for error
  119.         }
  120.         if ((*cdefHandle) != nil && errorState == noErr ) { // all is well
  121.             SInt8    state ;                                    // holding place for handle state
  122.             errorState = MyLockHandle(cdefHandle,&state);    
  123.             if (errorState == noErr) {
  124.                 UInt32            result;                        // the result we don't care about
  125.                 ControlDefUPP     myControlUPP;                // Holding place for the CDEF ProcPtr or UPP
  126.                                                             //
  127.                 myControlUPP = (ControlDefUPP)(*cdefHandle); 
  128.                 // What? Casting to a UPP? Are you crazy?
  129.                 // The reason you cast in instead of creating a UPP
  130.                 // is that it may already be a UPP (ie native CDEF) 
  131.                 // and dual UPP's would really confuse Mixed Mode. If its not
  132.                 // a upp, CallControlDefProc does the right thing by passing a 
  133.                 // a valid ProcInfo to CallUniversalProc which makes
  134.                 // mixed mode a happy camper in any case.  
  135.                 result = CallControlDefProc(myControlUPP,
  136.                                             GetControlVariant(ch),
  137.                                             ch,
  138.                                             calcCntlRgn,
  139.                                             (SInt32)theRgn);
  140.                 errorState = MySetHandleState(cdefHandle,state); // reset the handle state
  141.             }
  142.         }
  143.     } else {                                                 // ControlHandle or theRgn is nil                                                
  144.         errorState  = nilHandleErr;                            // set the error
  145.     }
  146.     return (errorState);                                    // be sure and return any errors
  147. }
  148.  
  149. //-------------------------------------------------------------------------
  150. // Simple routine to paint the region we get from the Control
  151. //-------------------------------------------------------------------------
  152.     static    OSErr DisplayControlRgn(ControlHandle ch)
  153. //-------------------------------------------------------------------------
  154. {
  155.     RgnHandle    theRgn;
  156.     SInt16         err = noErr;
  157.  
  158.     theRgn = NewRgn();                        // Get a region to work with
  159.     if (theRgn) {
  160.         err = GetControlRegion(ch,theRgn);    // Get the Button's Region
  161.         if (err == noErr){            
  162.             OffsetRgn(theRgn,kPaintRegionOffset,kNoOffset);        
  163.             PaintRgn(theRgn);
  164.             DisposeRgn(theRgn);
  165.         } else {
  166.            err = CheckMemoryError();
  167.         }
  168.     }
  169.     return (err);
  170. }
  171.  
  172.  
  173. //-------------------------------------------------------------------------
  174. // This gets called when the Click Me button is clicked.
  175. // ------------------------------------------------------------------------
  176. // Note!
  177. // There is a problem with global optimization and call back functions.
  178. // If you want global optimization on for the rest of your code you
  179. // should turn it off for any call back functions unless MW has released
  180. //  a fix. i.e #pragma optimization_level 1
  181. //-------------------------------------------------------------------------
  182.  pascal short DoButtonHit(ButtonItemRecHandle me, long  modifiers)
  183. //-------------------------------------------------------------------------
  184. {
  185. #pragma unused (modifiers)
  186.  
  187.     ControlRef     cr  = nil;
  188.     OSErr         err = noErr;
  189.     
  190.     cr = SAGetObjectRef(me);     
  191.     if (cr) {
  192.         err = DisplayControlRgn(cr);
  193.         if (err != noErr) {
  194.             ErrorMessage(kBadThingsMsg,err,kSANonFatalError);
  195.         }
  196.     }
  197.     return err;
  198. }
  199.  
  200. //-------------------------------------------------------------------------
  201. // This gets called when the Clear button is clicked.
  202. //-------------------------------------------------------------------------
  203. static pascal SInt16 DoClear(ButtonItemRef me, SInt32  modifiers)
  204. //-------------------------------------------------------------------------
  205. {
  206. #pragma unused (modifiers)
  207. #pragma unused (me)
  208.     Rect r;
  209.     
  210.     r = gSACurrentWindow->portRect;             // Get the window's portRect
  211.     r.left      += kPaintRegionOffset;                // offset so it doesn't erase
  212.     r.right  -= kScrollBarFudge;                // our buttons and scroll bar
  213.     r.bottom -= kScrollBarFudge;                // areas
  214.     InvalRect(&r);                                 
  215.     return noErr;                                
  216. }
  217.  
  218. //-------------------------------------------------------------------------
  219. // This is the main function. Note how simple it is. It installs
  220. // two Buttons and then lets SimpleApp handle the rest. 
  221. // 
  222. //-------------------------------------------------------------------------
  223.     void main(void)
  224. //-------------------------------------------------------------------------
  225. {
  226.     Rect     r;
  227.     SInt32    buttonID;
  228.     SInt16     gMyWindowID;
  229.     SInt16     err;
  230.     
  231.     InitSimpleApp(1,kUseStandardMenu);          // Simple App Sets up the Tool Box For us 
  232.     gMyWindowID = GetDocumentWindow (128);         // Get our stored window 
  233.                                                 // the global gSACurrentWindow is maintained
  234.                                                 // by SimpleApp and it contains the active
  235.                                                 // document window reference
  236.     SetWTitle(gSACurrentWindow,kOurWindowTitle);// set the window title so we know what we are running
  237.     SetRect(&r,10,30,100,50);                    // set the control bounds
  238.     err = InstallPushButton (&buttonID,            // Reference ID (we don't care)
  239.                              gSACurrentWindow,    // Owner Window 
  240.                              "\pClick Me",        // Name
  241.                              &r,                // Bounds                        
  242.                              kSANoCommandKey,    // Command Key
  243.                              DoButtonHit ,        // Button Hit 
  244.                              nil                // Button Update Proc 
  245.                              );
  246.     OffsetRect(&r,kNoOffset,kNextButtonOffset);                         
  247.     err = InstallPushButton (&buttonID,            // Reference ID (we don't care)
  248.                              gSACurrentWindow,    // Owner Window
  249.                              "\pClear",            // Name
  250.                              &r,                // Bounds                        
  251.                              kSANoCommandKey,    // Command Key
  252.                              DoClear ,            // Button Hit Proc
  253.                              nil                // Button Update Proc
  254.                              );
  255.     Run();                                         // Let SimpleApp handle the rest
  256. }
  257.  
  258.